package org.lhh.server.core.codec.database;

import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.lhh.server.common.utils.CollectionUtils;
import org.lhh.server.common.utils.JSONArray;
import org.lhh.server.common.utils.JSONObject;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.database.PartitionDatabaseMeta;
import org.pentaho.di.core.encryption.Encr;
import org.pentaho.di.core.exception.KettleDatabaseException;
import org.pentaho.di.core.plugins.DatabasePluginType;
import org.pentaho.di.core.plugins.PluginInterface;
import org.pentaho.di.core.plugins.PluginRegistry;
import org.pentaho.di.repository.StringObjectId;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@Data
public class DatabaseCodec {

    private static final Map<String, String> types = new LinkedHashMap<>();

    static {
        PluginRegistry registry = PluginRegistry.getInstance();
        List<PluginInterface> plugins = registry.getPlugins(DatabasePluginType.class);
        for (PluginInterface pluginInterface : plugins) {
            types.put(pluginInterface.getIds()[0], pluginInterface.getName());
        }
    }

    //一般
    private String id;
    private String displayName;
    private String url;
    private String type;
    private String typeDesc;
    private String hostname;
    private String databaseName;
    private String username;
    private String password;
    private String port;
    private String dataTablespace;
    private String indexTablespace;
    //高级
    private boolean supportBooleanDataType;
    private boolean supportTimestampDataType;
    private boolean quoteIdentifiersCheck;
    private boolean lowerCaseIdentifiersCheck;
    private boolean upperCaseIdentifiersCheck;
    private boolean preserveReservedCaseCheck;
    private String preferredSchemaName;
    private String connectSQL;
    //连接池
    private boolean usingConnectionPool;
    private int initialPoolSize;
    private int maximumPoolSize;
    private JSONArray poolParams;
    //选项
    private JSONArray attributes;
    //集群
    private boolean partitioned;
    private List<PartitionDatabaseCodec> partitionDatabaseList;

    private boolean edit;

    public static DatabaseCodec encode(DatabaseMeta databaseMeta) {
        DatabaseCodec databaseCodec = new DatabaseCodec();
        //一般
        databaseCodec.setId(databaseMeta.getObjectId().getId());
        databaseCodec.setDisplayName(databaseMeta.getDisplayName());
        try {
            databaseCodec.setUrl(databaseMeta.getURL());
        } catch (KettleDatabaseException ignored) {
        }
        databaseCodec.setType(databaseMeta.getPluginId());
        databaseCodec.setTypeDesc(types.get(databaseMeta.getPluginId()));
        databaseCodec.setHostname(databaseMeta.getHostname());
        databaseCodec.setDatabaseName(databaseMeta.getDatabaseName());
        databaseCodec.setUsername(databaseMeta.getUsername());
        databaseCodec.setPassword(Encr.encryptPasswordIfNotUsingVariables(databaseMeta.getPassword()));
        databaseCodec.setPort(databaseMeta.getDatabasePortNumberString());
        databaseCodec.setDataTablespace(databaseMeta.getDataTablespace());
        databaseCodec.setIndexTablespace(databaseMeta.getIndexTablespace());
        //高级
        databaseCodec.setSupportBooleanDataType(databaseMeta.supportsBooleanDataType());
        databaseCodec.setSupportTimestampDataType(databaseMeta.supportsTimestampDataType());
        databaseCodec.setQuoteIdentifiersCheck(databaseMeta.isQuoteAllFields());
        databaseCodec.setLowerCaseIdentifiersCheck(databaseMeta.isForcingIdentifiersToLowerCase());
        databaseCodec.setUpperCaseIdentifiersCheck(databaseMeta.isForcingIdentifiersToUpperCase());
        databaseCodec.setPreserveReservedCaseCheck(databaseMeta.preserveReservedCase());
        databaseCodec.setPreferredSchemaName(databaseMeta.getPreferredSchemaName());
        databaseCodec.setConnectSQL(databaseMeta.getConnectSQL());
        //连接池
        databaseCodec.setUsingConnectionPool(databaseMeta.isUsingConnectionPool());
        databaseCodec.setInitialPoolSize(databaseMeta.getInitialPoolSize());
        databaseCodec.setMaximumPoolSize(databaseMeta.getMaximumPoolSize());
        JSONArray poolParams = new JSONArray();
        Properties connectionPoolingProperties = databaseMeta.getConnectionPoolingProperties();
        for (Map.Entry<Object, Object> map : connectionPoolingProperties.entrySet()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("key", map.getKey());
            jsonObject.put("value", map.getValue());
            poolParams.add(jsonObject);
        }
        databaseCodec.setPoolParams(poolParams);
        //选项
        Map<String, String> extraOptions = databaseMeta.getExtraOptions();
        JSONArray attributes = new JSONArray();
        for (Map.Entry<String, String> extraOption : extraOptions.entrySet()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("key", extraOption.getKey().replace(databaseMeta.getPluginId() + ".", ""));
            jsonObject.put("value", extraOption.getValue());
            attributes.add(jsonObject);
        }
        databaseCodec.setAttributes(attributes);

        //集群
        databaseCodec.setPartitioned(databaseMeta.isPartitioned());
        PartitionDatabaseMeta[] clusterInformation = databaseMeta.getPartitioningInformation();
        databaseCodec.setPartitionDatabaseList(PartitionDatabaseCodec.decode(clusterInformation));

        return databaseCodec;
    }

    public static DatabaseMeta decode(DatabaseCodec databaseCodec) {
        DatabaseMeta databaseMeta = new DatabaseMeta();
        //一般
        databaseMeta.setName(databaseCodec.getDisplayName());
        databaseMeta.setDisplayName(databaseMeta.getName());
        databaseMeta.setDatabaseType(databaseCodec.getType());
        if (StringUtils.isNotEmpty(databaseCodec.getId()))
            databaseMeta.setObjectId(new StringObjectId(databaseCodec.getId()));
        databaseMeta.setHostname(databaseCodec.getHostname());
        databaseMeta.setDBName(databaseCodec.getDatabaseName());
        databaseMeta.setUsername(databaseCodec.getUsername());
        databaseMeta.setPassword(Encr.decryptPasswordOptionallyEncrypted(databaseCodec.getPassword()));
        databaseMeta.setStreamingResults(true);
        databaseMeta.setDBPort(databaseCodec.getPort());
        databaseMeta.setDataTablespace(databaseCodec.getDataTablespace());
        databaseMeta.setIndexTablespace(databaseCodec.getIndexTablespace());
        //连接池
        if (databaseCodec.isUsingConnectionPool())
            databaseMeta.setUsingConnectionPool(true);
        databaseMeta.setInitialPoolSize(databaseCodec.getInitialPoolSize());
        databaseMeta.setMaximumPoolSize(databaseCodec.getMaximumPoolSize());
        JSONArray poolParams = databaseCodec.getPoolParams();
        if (!CollectionUtils.isEmpty(poolParams)) {
            Properties properties = new Properties();
            for (int i = 0; i < poolParams.size(); i++) {
                JSONObject jsonObject = poolParams.getJSONObject(i);
                String parameter = jsonObject.optString("key");
                String value = jsonObject.optString("value");
                if (StringUtils.isNotEmpty(parameter) && StringUtils.isNotEmpty(value)) {
                    properties.setProperty(parameter, value);
                }
            }
            databaseMeta.setConnectionPoolingProperties(properties);
        }

        //选项
        JSONArray attributes = databaseCodec.getAttributes();
        if (!CollectionUtils.isEmpty(attributes)) {
            for (int i = 0; i < attributes.size(); i++) {
                JSONObject jsonObject = attributes.getJSONObject(i);
                String parameter = jsonObject.optString("key");
                String value = jsonObject.optString("value");
                if (StringUtils.isNotEmpty(parameter) && StringUtils.isNotEmpty(value)) {
                    databaseMeta.addExtraOption(databaseMeta.getPluginId(), parameter, value);
                }
            }
        }
        //高级
        databaseMeta.setSupportsBooleanDataType(databaseCodec.isSupportBooleanDataType());
        databaseMeta.setSupportsTimestampDataType(databaseCodec.isSupportTimestampDataType());
        databaseMeta.setQuoteAllFields(databaseCodec.isQuoteIdentifiersCheck());
        databaseMeta.setForcingIdentifiersToLowerCase(databaseCodec.isLowerCaseIdentifiersCheck());
        databaseMeta.setForcingIdentifiersToUpperCase(databaseCodec.isUpperCaseIdentifiersCheck());
        databaseMeta.setPreserveReservedCase(databaseCodec.isPreserveReservedCaseCheck());
        databaseMeta.setPreferredSchemaName(databaseCodec.getPreferredSchemaName());
        databaseMeta.setConnectSQL(databaseCodec.getConnectSQL());

        //集群
        // Cluster panel settings
        databaseMeta.setPartitioned(databaseCodec.isPartitioned());
        List<PartitionDatabaseCodec> partitionDatabaseList = databaseCodec.getPartitionDatabaseList();
        databaseMeta.setPartitioningInformation(PartitionDatabaseCodec.encode(partitionDatabaseList));
        return databaseMeta;
    }
}
